<template>
  <div
    ref="DraggableVertical"
    class="draggable-vertical"
    :class="{ toggled, bottom: side === 'bottom' }"
    :style="{
      minHeight: calcMinHeight + 'px',
      maxHeight: maxHeight + 'px',
      height: height + 'px'
    }"
  >
    <div class="draggable-vertical__content" v-show="!toggled">
      <slot name="content"></slot>
    </div>
    <div
      id="dragHandler"
      v-show="!toggled"
      class="border-handler"
      :style="{
        bottom: side === 'top' ? '-3px' : 'auto',
        top: side === 'bottom' ? '-3px' : 'auto'
      }"
      @mousedown.stop.prevent="onMouseDown"
    ></div>
    <!-- <sider-toggle
      slot="toggle"
      class="tree-toggle"
      :side="side"
      @click="onToggle"
    /> -->
  </div>
</template>

<script>
import SiderToggle from './SiderToggle.vue'
let currentY = 0
let currentHeight = 0
export default {
  name: 'DraggableVertical',
  components: {
    SiderToggle
  },
  props: {
    defaultHeight: {
      type: String | Number,
      default: 150
    },
    minHeight: {
      type: String | Number,
      default: 50
    },
    siblingMinHeight: {
      type: String | Number,
      default: 0
    },
    side: {
      type: String,
      default: 'top' // top 暂不支持bottom
    }
  },
  data () {
    return {
      toggled: false,
      dragging: false,
      calcMinHeight: 0,
      maxHeight: 'none',
      originHeight: 0, // 用于记录toggle前的height
      height: 0,
      clientHeight: 0
    }
  },

  created () {
    this.calcMinHeight =
      typeof this.minHeight === 'string'
        ? parseInt(this.minHeight)
        : this.minHeight
    this.originHeight = this.height =
      typeof this.defaultHeight === 'string'
        ? parseInt(this.defaultHeight)
        : this.defaultHeight
  },

  mounted () {
    document.documentElement.addEventListener(
      'mousemove',
      this.onMouseMove,
      true
    )
    document.documentElement.addEventListener('mouseup', this.onMouseUp, true)
    this.calcHeight()
  },
  beforeDestroy () {
    document.documentElement.removeEventListener('mousemove', this.onMouseMove)
    document.documentElement.removeEventListener('mouseup', this.onMouseUp)
  },

  methods: {
    calcHeight () {
      const parentNode = this.$refs.DraggableVertical.parentNode
      this.clientHeight = parentNode.clientHeight
      const siblingMinHeight =
        typeof this.siblingMinHeight === 'string'
          ? parseInt(this.siblingMinHeight)
          : this.siblingMinHeight
      this.maxHeight = Math.max(
        (this.clientHeight && this.clientHeight - siblingMinHeight) ||
          document.documentElement.clientHeight - 150 - siblingMinHeight,
        parseInt(this.minHeight)
      )
    },
    onToggle () {
      this.toggled = !this.toggled
      if (this.toggled) {
        this.height = 0
        this.calcMinHeight = 0
        this.maxHeight = 0
      } else {
        this.height = this.originHeight
        this.calcMinHeight =
          typeof this.minHeight === 'string'
            ? parseInt(this.minHeight)
            : this.minHeight
        this.maxHeight = this.originHeight
        setTimeout(() => {
          // 为了让展开和收起的速度一致，先把maxHeight放开到原宽度，过0.2s再设置为view的一半
          this.maxHeight = Math.max(
            this.clientHeight / 2 ||
              (document.documentElement.clientHeight - 150) / 2,
            parseInt(this.minHeight)
          )
        }, 200)
      }
      this.$emit('toggle')
    },

    onMouseDown (e) {
      this.dragging = true
      currentY = e.clientY
      currentHeight = parseInt(this.height)
    },

    onMouseMove (e) {
      if (!this.dragging) return
      const deltaX = e.clientY - currentY
      let finalHeight = 0
      if (this.side === 'top') {
        finalHeight = currentHeight + deltaX
      } else if (this.side === 'bottom') {
        finalHeight = currentHeight - deltaX
      }
      this.height = Math.min(
        Math.max(finalHeight, parseInt(this.minHeight)),
        parseInt(this.maxHeight)
      )
      this.$emit('getHeight', this.height)
    },

    onMouseUp (e) {
      if (this.dragging) {
        this.dragging = false
        this.originHeight = this.height
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.draggable-vertical {
  position: relative;
  width: 100%;
  // box-shadow: 2px 4px 6px 0 #e4e4e4;
  transition: min-height 0.2s, max-height 0.2s;

  &__content {
    height: 100%;
    width: 100%;
    overflow-x: auto;
  }

  .border-handler {
    position: absolute;
    width: 100%;
    height: 6px;
    left: 0;
    bottom: -3px;
    cursor: row-resize;
  }

  .tree-toggle {
    position: absolute;
    left: 50%;
    bottom: 10px;
    top: auto;
    transform: translateX(-50%);
    opacity: 0;
    z-index: 999;
    transition: opacity 0.3s;
  }

  &:hover {
    .tree-toggle {
      opacity: 1;
    }
  }

  &.bottom {
    box-shadow: 0 4px 6px 0 #e4e4e4;
    position: absolute;
    bottom: 0;
    .tree-toggle {
      top: -40px;
      bottom: auto;
    }
  }

  &.toggled {
    .tree-toggle {
      opacity: 1;
    }
  }
}
</style>
